/**
 * 脚本名称：PP 停车
 * 活动规则：每日签到可获取积分，积分有效期≤2年。
 * 脚本说明：Node.js 版本，支持多账号
 * 环境变量：PP_TOKEN
 * 更新时间：2024-03-13 修复 Token 格式问题，添加本地通知模块
 ##cron: 20 9 * * *
##new Env("PP停车")
 */

const axios = require('axios');
const path = require('path');
const fs = require('fs');

class PPCarParking {
    constructor() {
        this.name = 'PP 停车';
        this.messages = [];
        this.token = process.env['PP_TOKEN'] || '';
        this.tokenArr = this.token ? this.token.split(',') : [];
        this.app_id = 'wxa204074068ad40ef';
        this.nickname = '';
        this.identity = '';
        this.mobile = '';
        
        // 动态引入本地通知模块
        this.notify = this.loadNotifyModule();
    }

    // 加载本地通知模块
    loadNotifyModule() {
        try {
            // 尝试多种可能的路径
            const possiblePaths = [
                './sendNotify.js',
                './utils/sendNotify.js',
                path.join(__dirname, 'sendNotify.js'),
                path.join(__dirname, 'utils', 'sendNotify.js')
            ];
            
            for (const modulePath of possiblePaths) {
                if (fs.existsSync(modulePath.replace('.js', '')) || 
                    fs.existsSync(modulePath)) {
                    const notifyModule = require(modulePath);
                    console.log(`✅ 成功加载通知模块: ${modulePath}`);
                    return notifyModule;
                }
            }
            
            console.log('⚠️ 未找到本地通知模块，将使用控制台输出');
            return null;
        } catch (error) {
            console.log(`❌ 加载通知模块失败: ${error.message}`);
            return null;
        }
    }

    log(message) {
        console.log(`[${new Date().toLocaleString()}] ${message}`);
    }

    async main() {
        if (this.tokenArr.length) {
            this.log(`找到 ${this.tokenArr.length} 个 Token 变量 ✅`);
            for (let i = 0; i < this.tokenArr.length; i++) {
                this.log(`----- 账号 [${i + 1}] 开始执行 -----`);
                
                // 初始化
                this.nickname = '';
                this.identity = '';
                this.mobile = '';
                let currentToken = this.tokenArr[i].trim();
                
                // 确保 Token 不为空
                if (!currentToken) {
                    this.log(`❌ Token 为空，跳过账号 ${i + 1}`);
                    continue;
                }
                
                // 检查 Token 格式，确保是有效的 JWT
                if (!this.isValidToken(currentToken)) {
                    this.log(`❌ Token 格式无效，跳过账号 ${i + 1}`);
                    continue;
                }
                
                this.log(`ℹ️ 使用的 Token: ${currentToken.substring(0, 20)}...`);

                // 用户信息
                const userInfo = await this.whoami(currentToken);
                if (!userInfo) continue;

                // 用户积分
                await this.balance(currentToken);
                // 执行任务
                await this.task(currentToken);
            }
            this.log(`----- 所有账号执行完成 -----`);
        } else {
            throw new Error('未找到 Token 变量 ❌');
        }
    }

    // 检查 Token 格式
    isValidToken(token) {
        // JWT Token 通常由三部分组成，用点分隔
        const parts = token.split('.');
        if (parts.length !== 3) {
            return false;
        }
        
        // 检查每部分的长度
        try {
            // 尝试解码 payload 部分
            const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString());
            return payload && typeof payload === 'object';
        } catch (e) {
            return false;
        }
    }

    // 获取任务列表
    async task(token) {
        let msg = '';
        const params = {
            app_id: this.app_id
        };
        
        try {
            const result = await this.request({
                method: 'GET',
                url: `https://user-api.4pyun.com/rest/2.0/bonus/reward/task/list?${this.serializeParams(this.getEncryptKeys(params))}`,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': `Bearer ${token}`
                }
            });

            if (result?.code == "1001") {
                this.log(`任务列表获取成功 ✅`);
                const row = result['payload']['row'];

                // 获取最大任务次数
                const repeatLimit = row.reduce((max, item) => {
                    if (item.referer_url.includes('voucher=')) {
                        return Math.max(max, item.repeat_limit);
                    } else {
                        return max;
                    }
                }, 0);

                for (let i = 0; i < repeatLimit; i++) {
                    for (const item of row) {
                        const purpose = item['purpose'];
                        const taskName = i > 0 ? item['name'] + (i + 1) : item['name'];
                        if (item['referer_url'].includes('voucher=')) {
                            const voucher = new URLSearchParams(item['referer_url']).get('voucher');
                            this.log(`✈️ 执行任务: ${taskName}`);
                            const completed = await this.complete(purpose, voucher, token);
                            if (completed) {
                                await this.acquire(purpose, taskName, token);
                            }
                        } else if (taskName.includes('签到')) {
                            this.log(`✈️ 执行任务: ${taskName}`);
                            await this.acquire(purpose, taskName, token);
                        }
                    }
                    if (repeatLimit == i + 1) break;
                    
                    // 更新任务列表
                    const newResult = await this.request({
                        method: 'GET',
                        url: `https://user-api.4pyun.com/rest/2.0/bonus/reward/task/list?${this.serializeParams(this.getEncryptKeys(params))}`,
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'Authorization': `Bearer ${token}`
                        }
                    });
                    
                    if (newResult?.code == "1001") {
                        this.log(`更新任务列表成功 ✅`);
                    } else {
                        break;
                    }
                }
            } else {
                msg = `任务列表获取失败: ${result?.message || '未知错误'}`;
            }
        } catch (error) {
            msg = `任务列表获取失败: ${error.message}`;
        }
        
        if (msg) {
            this.messages.push(msg);
            this.log(msg);
        }
    }

    // 执行任务
    async complete(purpose, voucher, token) {
        try {
            const result = await this.request({
                method: 'POST',
                url: 'https://user-api.4pyun.com/rest/2.0/bonus/reward/task/complete',
                headers: {
                    'Content-Type': 'application/json;charset=utf-8',
                    'Authorization': `Bearer ${token}`
                },
                data: this.encryption(
                    JSON.stringify({
                        purpose,
                        voucher,
                        app_id: this.app_id
                    })
                )
            });

            return result?.code == "1001";
        } catch (error) {
            this.log(`完成任务失败: ${error.message}`);
            return false;
        }
    }

    // 领取奖励 / 签到
    async acquire(purpose, taskName, token) {
        let msg = '';
        const params = {
            purpose,
            app_id: this.app_id
        };
        
        try {
            const result = await this.request({
                method: 'GET',
                url: `https://user-api.4pyun.com/rest/2.0/bonus/reward/acquire?${this.serializeParams(this.getEncryptKeys(params))}`,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': `Bearer ${token}`
                }
            });

            if (result?.code == "1001") {
                msg = `${taskName} 任务完成, 获得 ${result['payload']['value']} 积分 🎉`;
            } else if (result?.code == "1002") {
                msg = `${taskName} 任务已完成 ✅`;
            } else {
                msg = `${taskName} 任务失败: ${result?.message || '未知错误'}`;
            }
        } catch (error) {
            msg = `${taskName} 任务失败: ${error.message}`;
        }

        if (msg) {
            this.messages.push(msg);
            this.log(msg);
        }
    }

    // 获取用户信息
    async whoami(token) {
        let success = false;
        
        try {
            const result = await this.request({
                method: 'GET',
                url: 'https://user-api.4pyun.com/rest/2.0/user/whoami',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': `Bearer ${token}`
                }
            });

            if (result?.code == "1001") {
                const { identity, mobile, nickname } = result.payload;
                this.identity = identity;
                this.mobile = mobile;
                this.nickname = nickname;
                this.log(`✅ 用户信息获取成功 - 昵称: ${nickname}`);
                success = true;
            } else if (result?.code == "401") {
                this.log(`❌ Token 已失效`);
            } else if (result?.code == "400") {
                this.log(`❌ Token 格式错误: ${result.hint || result.message}`);
            } else {
                this.log(`❌ 用户信息获取失败: ${result?.message || JSON.stringify(result)}`);
            }
        } catch (error) {
            this.log(`❌ 用户信息获取失败: ${error.message}`);
        }
        
        return success;
    }

    // 获取用户积分
    async balance(token) {
        let msg = '';
        const params = {
            user_id: this.identity,
            user_type: 1,
            identity: this.identity
        };
        
        try {
            const result = await this.request({
                method: 'GET',
                url: `https://user-api.4pyun.com/rest/2.0/reward/balance?${this.serializeParams(this.getEncryptKeys(params))}`,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': `Bearer ${token}`
                }
            });

            if (result?.code == "1001") {
                msg = `昵称: ${this.nickname}  积分: ${result.payload.balance}`;
                this.log(`✅ 用户积分获取成功`);
            } else {
                msg = `❌ 用户积分获取失败: ${result?.message || JSON.stringify(result)}`;
            }
        } catch (error) {
            msg = `❌ 用户积分获取失败: ${error.message}`;
        }
        
        if (msg) {
            this.messages.push(msg);
            this.log(msg);
        }
    }

    // 请求函数
    async request(options) {
        try {
            const config = {
                method: options.method || 'GET',
                url: options.url,
                headers: options.headers,
                timeout: 15000
            };

            if (options.data) {
                config.data = options.data;
            }

            const response = await axios(config);
            return response.data;
        } catch (error) {
            if (error.response) {
                return error.response.data;
            }
            throw error;
        }
    }

    // 加密 GET 请求数据
    getEncryptKeys(n) {
        const r = {};
        if (n && Object.keys(n).length > 0) {
            for (const t in n) {
                const e = n[t];
                if (null != e && null != e) {
                    r[this.encryption(t)] = e instanceof Array ? 
                        e.map(n => this.encryption(n.toString())) : 
                        this.encryption(e.toString());
                }
            }
        }
        return r;
    }

    // 序列化字符串
    serializeParams(n) {
        const o = [];
        for (const a in n) {
            if (n.hasOwnProperty(a)) {
                const r = n[a];
                if (null != r) {
                    if (Array.isArray(r)) {
                        for (const i of r) {
                            o.push(`${encodeURIComponent(a)}=${encodeURIComponent(i)}`);
                        }
                    } else {
                        o.push(`${encodeURIComponent(a)}=${encodeURIComponent(r)}`);
                    }
                }
            }
        }
        return o.join("&");
    }

    // 加密函数
    encryption(r) {
        const base64Encode = (input) => {
            const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
            let output = "";
            let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            let i = 0;
            
            while (i < input.length) {
                chr1 = input[i++];
                chr2 = i < input.length ? input[i++] : Number.NaN;
                chr3 = i < input.length ? input[i++] : Number.NaN;
                
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output += keyStr.charAt(enc1) + keyStr.charAt(enc2) + 
                         keyStr.charAt(enc3) + keyStr.charAt(enc4);
            }
            return output;
        };

        const stringToBytes = (str) => {
            const bytes = [];
            for (let i = 0; i < str.length; i++) {
                const charCode = str.charCodeAt(i);
                if (charCode < 0x80) {
                    bytes.push(charCode);
                } else if (charCode < 0x800) {
                    bytes.push(0xc0 | (charCode >> 6));
                    bytes.push(0x80 | (charCode & 0x3f));
                } else if (charCode < 0x10000) {
                    bytes.push(0xe0 | (charCode >> 12));
                    bytes.push(0x80 | ((charCode >> 6) & 0x3f));
                    bytes.push(0x80 | (charCode & 0x3f));
                } else {
                    bytes.push(0xf0 | (charCode >> 18));
                    bytes.push(0x80 | ((charCode >> 12) & 0x3f));
                    bytes.push(0x80 | ((charCode >> 6) & 0x3f));
                    bytes.push(0x80 | (charCode & 0x3f));
                }
            }
            return bytes;
        };

        const xorEncrypt = (data, key) => {
            const result = new Uint8Array(data.length);
            for (let i = 0; i < data.length; i++) {
                const keyChar = key.charCodeAt((data.length - i) % 32);
                result[i] = keyChar ^ ~data[i];
            }
            return result;
        };

        const key = "riegh^ee:w0fok5je5eeS{eecaes1nep";
        const bytes = stringToBytes(r);
        const encrypted = xorEncrypt(bytes, key);
        return base64Encode(encrypted);
    }

    // 发送通知
    async sendNotify(message) {
        if (!message) return;
        
        const title = 'PP停车';
        
        if (this.notify && typeof this.notify.sendNotify === 'function') {
            try {
                await this.notify.sendNotify(title, message);
                this.log(`✅ 已发送通知: ${title}`);
            } catch (error) {
                this.log(`❌ 发送通知失败: ${error.message}`);
                // 降级到控制台输出
                this.log(`\n----- ${title} -----\n${message}`);
            }
        } else {
            // 没有通知模块，使用控制台输出
            this.log(`\n----- ${title} -----\n${message}`);
        }
    }
}

// 主执行函数
async function main() {
    const pp = new PPCarParking();
    
    try {
        await pp.main();
    } catch (error) {
        pp.messages.push(error.message);
        pp.log(`执行出错: ${error.message}`);
    } finally {
        await pp.sendNotify(pp.messages.join('\n').trim());
    }
}

// 执行脚本
if (require.main === module) {
    main().catch(console.error);
}

module.exports = PPCarParking;